package com.skyline.feed.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.skyline.feed.dao.PersonalFeedDao;
import com.skyline.feed.dao.SubscribedFeedDao;
import com.skyline.feed.model.FeedResult;
import com.skyline.feed.service.SubscribedFeedService;

/**
 * 订阅推信的实现
 * 
 * @author Jairus Chan
 *
 */
@Service("subscribedFeedService")
public class SubscribedFeedServiceImpl implements SubscribedFeedService {

	@Value("${feed.column.time}")
	private String TIME;

//	@Value("${feed.column.resourceId}")
//	private String RESOURCE_ID;
//
//	@Value("${feed.column.resourceId.Title}")
//	private String TITLE;
//
//	@Value("${feed.column.content}")
//	private String CONTENT;
//
//	@Value("${feed.column.providerId}")
//	private String PROVIDER_ID;
//
//	@Value("${feed.column.providerNickname}")
//	private String PROVIDER_NICKNAME;
//
//	@Value("${feed.column.providerPortrait}")
//	private String PROVIDER_PORTRAIT;
//
//	@Value("${feed.column.ownerId}")
//	private String OWNER_ID;
//
//	@Value("${feed.column.type}")
//	private String TYPE;

	@Value("${feed.pagination.minPageSize}")
	private Integer MIN_PAGE_SIZE;

	@Value("${feed.pagination.pageSize}")
	private Integer PAGE_SIZE;

	@Value("${feed.subscribedFeed.maxFeedLevel}")
	private Integer MAX_FEED_LEVEL;

	@Value("${feed.maxFeedLife}")
	private Long MAX_FEED_LIFE;

	@Autowired
	private SubscribedFeedDao subscribedFeedDao;

	@Autowired
	private PersonalFeedDao personalFeedDao;

	/**
	 * 此方法用于生成一个等级为level的返回数据列表
	 * 
	 * @param idolIds
	 *            观注者列表（偶像列表）
	 * @param ownerId
	 *            用户的Id
	 * @param current
	 *            当前的记录
	 * @param level
	 *            等级
	 * @return
	 */
	private List<DBObject> getFeedsImpl(List<Long> idolIds, Long ownerId, Integer current, Integer level) {
		List<DBObject> returnFeeds = null;
		// 当为第一次访问这个订阅库的时候，需要查询这个订阅库中发布时间最大的记录，以用于查询是否还有记录没有订阅过来
		//Tested
		if (current == 0) {
			// 查询最新的记录
			//Tested
			DBObject newestFeed = subscribedFeedDao.queryNewestFeed(ownerId, level);
			// 当有最新的记录时，根据最新的记录查询是是否有记录没有订阅过来;不然，则认为用户没有这个库的时间断的记录，需要重新订阅所有的记录
			//Tested
			Long lastQueryTime = (new Date()).getTime() - MAX_FEED_LIFE;
			//Tested
			if (newestFeed != null) {
				lastQueryTime = (Long) newestFeed.get(TIME);
			}
			
			//查询没有被订阅的记录
			//Tested
			DBCursor cursor = personalFeedDao.queryFeeds(idolIds, level, lastQueryTime);
			//Tested
			List<DBObject> newFeeds = cursor.toArray();
			//System.out.println(newFeeds.size());
			if ((newFeeds != null && newFeeds.size() > 0)) {
				//当查询到没有被订阅的记录时，就将其插入到订阅库中去
				//Tested
				subscribedFeedDao.insertFeeds(newFeeds, ownerId);
				if (newFeeds.size() > PAGE_SIZE) {
					//Tested
					returnFeeds = newFeeds.subList(0, PAGE_SIZE);
				} else {
					//Tested
					returnFeeds = newFeeds;
				}
			} else {
				//Tested
				returnFeeds = new ArrayList<DBObject>();
			}
		} else {
			//Tested
			returnFeeds = new ArrayList<DBObject>();
		}
		//System.out.println(returnFeeds.size());
		//当没有被记录的记录数据没有达到最小分页大小时，从订阅库中取PAGE_SIZE - returnFeeds.size()条记录
		if (returnFeeds.size() < MIN_PAGE_SIZE) {
			//Tested
			List<DBObject> feeds = subscribedFeedDao.queryFeeds(ownerId, current+returnFeeds.size(), current+PAGE_SIZE, level);
			returnFeeds.addAll(feeds);
		}
		return returnFeeds;
	}

	@Override
	public FeedResult getFeeds(List<Long> idolIds, Long ownerId, Integer current, Integer level) {
		List<Long> idolIdsAction=idolIds;
		idolIdsAction.add(ownerId);
		FeedResult result = new FeedResult();
		List<DBObject> returnFeeds = this.getFeedsImpl(idolIdsAction, ownerId, current, level);
		current=current+returnFeeds.size();
		//当记录数依然少于最小分页时，说明在这个分库的数据已经找完了，应到下一级的分库中
		while (returnFeeds.size() < MIN_PAGE_SIZE) {
			if (level >= MAX_FEED_LEVEL) {
				//Tested
				break;
			} else {
				level = level + 1;
				current = 0;
				List<DBObject> feeds = this.getFeedsImpl(idolIdsAction, ownerId, current, level);
				returnFeeds.addAll(feeds);
				current = feeds.size();
			}
		}
		result.setCurrent(current);
		result.setData(returnFeeds);
		result.setLevel(level);
		return result;
	}

	@Override
	public List<DBObject> getNewFeeds(List<Long> idolIds, Long ownerId, Long lastQueryTime) {
		List<Long> idolIdsAction=idolIds;
		idolIdsAction.add(ownerId);
		DBCursor cursor = personalFeedDao.queryFeeds(idolIdsAction, 0, lastQueryTime);
		List<DBObject> newFeeds = cursor.toArray();
		subscribedFeedDao.insertFeeds(newFeeds, ownerId);
		return newFeeds;
	}
}
